# AW9523 16通道GPIO扩展芯片驱动
# 简化版本：仅提供设置和读取端口电平功能


# BTN_A P00
# BTN_B P01
# KEY_PRESS P17
# KEY_UP P15
# KEY_DOWN P07
# KEY_LEFT P14
# KEY_RIGHT P16


class wm_aw9523:
    """AW9523 GPIO扩展芯片驱动类 - 简化版本"""

    # AW9523寄存器地址
    AW9523_ADDR = 0x58  # 默认I2C地址
    REG_INPUT_PORT0 = 0x00      # 输入端口0 (P00-P07)
    REG_INPUT_PORT1 = 0x01      # 输入端口1 (P10-P17)
    REG_OUTPUT_PORT0 = 0x02     # 输出端口0 (P00-P07)
    REG_OUTPUT_PORT1 = 0x03     # 输出端口1 (P10-P17)
    REG_CONFIG_PORT0 = 0x04     # 配置端口0 (P00-P07)
    REG_CONFIG_PORT1 = 0x05     # 配置端口1 (P10-P17)
    REG_ID = 0x10               # 芯片ID

    def __init__(self, i2c=None, addr=None):
        """
        初始化AW9523

        Args:
            i2c: I2C对象，如果为None则使用全局i2c
            addr: I2C地址，如果为None则使用默认地址0x58
        """
        if i2c is None:
            # 使用全局I2C对象
            try:
                # 直接使用全局变量i2c
                import __main__
                if hasattr(__main__, 'i2c'):
                    self.i2c = __main__.i2c
                else:
                    # 尝试从builtins获取
                    import builtins
                    if hasattr(builtins, 'i2c'):
                        self.i2c = builtins.i2c
                    else:
                        raise RuntimeError("未找到I2C对象，请先初始化I2C")
            except Exception as e:
                raise RuntimeError(f"未找到I2C对象，请先初始化I2C: {e}")
        else:
            self.i2c = i2c

        self.addr = addr or self.AW9523_ADDR

        # 验证芯片
        if not self._check_id():
            raise RuntimeError(f"未找到AW9523芯片 (地址: 0x{self.addr:02X})")

        # 初始化配置：所有端口设为输入模式
        self._init_config()

    def _check_id(self):
        """检查芯片ID"""
        try:
            chip_id = self._read_reg(self.REG_ID)
            return chip_id == 0x23  # AW9523的芯片ID
        except:
            return False

    def _init_config(self):
        """初始化配置：所有端口设为输入模式"""
        # 设置所有端口为输入模式 (1=输入, 0=输出)
        self._write_reg(self.REG_CONFIG_PORT0, 0xFF)  # P00-P07 输入
        self._write_reg(self.REG_CONFIG_PORT1, 0xFF)  # P10-P17 输入
        # 设置P10为输出模式
        self._write_reg(self.REG_CONFIG_PORT1, 0x01)

        # 初始化输出状态为低电平
        self._write_reg(self.REG_OUTPUT_PORT0, 0x00)
        self._write_reg(self.REG_OUTPUT_PORT1, 0x00)

    def _read_reg(self, reg):
        """读取寄存器"""
        data = self.i2c.readfrom_mem(self.addr, reg, 1)
        return data[0]

    def _write_reg(self, reg, value):
        """写入寄存器"""
        self.i2c.writeto_mem(self.addr, reg, bytes([value]))

    def set_pin(self, port, pin, level):
        """
        设置指定引脚的电平

        Args:
            port: 端口号 (0 或 1)
            pin: 引脚号 (0-7)
            level: 电平 (True=高电平, False=低电平)
        """
        if port not in [0, 1] or pin not in range(8):
            raise ValueError("端口号必须为0或1，引脚号必须为0-7")

        # 先设置为输出模式
        config_reg = self.REG_CONFIG_PORT0 if port == 0 else self.REG_CONFIG_PORT1
        current_config = self._read_reg(config_reg)
        current_config &= ~(1 << pin)  # 清除对应位，设为输出模式
        self._write_reg(config_reg, current_config)

        # 设置输出电平
        output_reg = self.REG_OUTPUT_PORT0 if port == 0 else self.REG_OUTPUT_PORT1
        current_output = self._read_reg(output_reg)
        if level:
            current_output |= (1 << pin)    # 设置高电平
        else:
            current_output &= ~(1 << pin)   # 设置低电平
        self._write_reg(output_reg, current_output)

    def read_pin(self, port, pin):
        """
        读取指定引脚的电平

        Args:
            port: 端口号 (0 或 1)
            pin: 引脚号 (0-7)

        Returns:
            bool: True=高电平, False=低电平
        """
        if port not in [0, 1] or pin not in range(8):
            raise ValueError("端口号必须为0或1，引脚号必须为0-7")

        # 确保为输入模式
        config_reg = self.REG_CONFIG_PORT0 if port == 0 else self.REG_CONFIG_PORT1
        current_config = self._read_reg(config_reg)
        if not (current_config & (1 << pin)):  # 如果不是输入模式
            current_config |= (1 << pin)       # 设为输入模式
            self._write_reg(config_reg, current_config)

        # 读取输入电平
        input_reg = self.REG_INPUT_PORT0 if port == 0 else self.REG_INPUT_PORT1
        value = self._read_reg(input_reg)
        return bool(value & (1 << pin))

    def get_key_state(self, key_name):
        """
        获取指定按键状态

        Args:
            key_name: 按键名称，支持以下值：
                'BTN_A', 'BTN_B', 'KEY_PRESS', 'KEY_UP', 'KEY_DOWN', 'KEY_LEFT', 'KEY_RIGHT'

        Returns:
            bool: True=按下, False=释放
        """
        # 按键映射表
        key_map = {
            'BTN_A': (0, 0),      # P00
            'BTN_B': (0, 1),      # P01
            'KEY_PRESS': (1, 7),  # P17
            'KEY_UP': (1, 5),     # P15
            'KEY_DOWN': (0, 7),   # P07
            'KEY_LEFT': (1, 4),   # P14
            'KEY_RIGHT': (1, 6)   # P16
        }

        if key_name not in key_map:
            raise ValueError(f"无效的按键名称: {key_name}。支持: {list(key_map.keys())}")

        port, pin = key_map[key_name]
        return self.read_pin(port, pin)

    def get_all_keys_state(self):
        """
        获取所有按键状态

        Returns:
            dict: 按键状态字典，格式: {'BTN_A': True, 'BTN_B': False, ...}
        """
        keys = ['BTN_A', 'BTN_B', 'KEY_PRESS', 'KEY_UP',
                'KEY_DOWN', 'KEY_LEFT', 'KEY_RIGHT']
        states = {}

        for key in keys:
            states[key] = self.get_key_state(key)

        return states

    def monitor_pins(self, interval=0.1, show_changes_only=False):
        """
        循环读取所有引脚状态

        Args:
            interval: 读取间隔时间(秒)，默认0.1秒
            show_changes_only: 是否只显示变化，默认False
        """
        print(f"开始监控所有引脚状态 (间隔: {interval}秒)")
        print("按 Ctrl+C 停止监控")
        print("=" * 50)

        last_states = {}
        count = 0

        try:
            while True:
                current_states = {}
                changed = False

                # 读取所有引脚状态
                for port in [0, 1]:
                    for pin in range(8):
                        try:
                            level = self.read_pin(port, pin)
                            current_states[(port, pin)] = level

                            # 检查状态变化
                            if (port, pin) not in last_states or last_states[(port, pin)] != level:
                                changed = True
                                if not show_changes_only:
                                    status = "高" if level else "低"
                                    print(f"[{count:4d}] P{port}{
                                          pin:02d}: {status}")
                        except Exception as e:
                            print(f"读取P{port}{pin:02d}出错: {e}")

                # 显示变化或定期显示
                if changed or (not show_changes_only and count % 10 == 0):
                    if show_changes_only:
                        print(f"\n[{count:4d}] 状态变化:")
                        for (port, pin), level in current_states.items():
                            if (port, pin) not in last_states or last_states[(port, pin)] != level:
                                status = "高" if level else "低"
                                print(f"  P{port}{pin:02d}: {status}")
                    else:
                        print(f"[{count:4d}] 监控中...")

                last_states = current_states.copy()
                count += 1

                import time
                time.sleep(interval)

        except KeyboardInterrupt:
            print(f"\n监控已停止，共读取 {count} 次")
